package com.xbongbong.parent.parse.data;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.pojo.vo.LinkResultDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.LinkDataPojo;
import com.xbongbong.pro.formdata.pojo.vo.FormDataVO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author: wufeng
 * @date: 2018/11/9 15:40
 * @desrcption: 表单数据列表处理关联数据的问题
 */
@Component
public class FormDataLinkDataListServiceImpl extends BaseFormDataLinkDataHelp  {

    private static  final Logger LOG = LoggerFactory.getLogger(FormDataLinkDataListServiceImpl.class);

    @Resource
    private LinkDataHelp linkDataHelp;


    /**
     * 关联数据的数据查询
     * @param linkResultDataDTO
     * @param linkResultDataVO 关联数据容器
     * @return
     * @throws XbbException
     */
    public Map<String, Object> formDataLinkDataGet(LinkResultDataDTO linkResultDataDTO, LinkResultDataVO linkResultDataVO) throws XbbException {
        Map<String, Object> resultDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        try {

            Map<String, FieldAttrEntity> explainMap = linkResultDataVO.getExplainMap();
            Map<String, Map<String, FieldAttrEntity>> subExplainMap = new HashMap<>(linkResultDataVO.getExplainList().size());
            Set<String> linkAttrSet = new HashSet<>();
            List<LinkInfoPojo> linkInfoList = new ArrayList<>();
            linkResultDataVO.getExplainList().forEach(item->{
                if (ExplainUtil.isSubForm(item.getFieldType())) {
                    List<? extends FieldAttrEntity> jsonArray = item.getSubForm().getItems();
                    for (int i = 0; i < jsonArray.size(); i++) {
                        FieldAttrEntity subForm = jsonArray.get(i);
                        if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), subForm.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), subForm.getFieldType())) {
                            linkInfoList.add(subForm.getLinkInfo());
                            linkAttrSet.add(item.getAttr() + StringConstant.POINT + subForm.getAttr());

                        }
                    }
                } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), item.getFieldType())) {
                    linkInfoList.add(item.getLinkInfo());
                    linkAttrSet.add(item.getAttr());
                }
            });


            List<Long> formIdList = new ArrayList<>();
            List<Long> workOrderFormIdList = new ArrayList<>();
            for (LinkInfoPojo linkInfoPojo : linkInfoList) {
                if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                    workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
                } else {
                    formIdList.add(linkInfoPojo.getLinkFormId());
                }
            }
            Set<String> linkDataSet = new HashSet<>(); // 主数据的关联数据字段
            Map<String, Set<String>> subFormLinkDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY); // key是子表单字段 value是这个子表单里面得所有关联数据字段
            List<PaasFormDataEntityExt> formDataEsList = linkResultDataVO.getFormDataList();
            // 解析子表单中的关联数据字段
            FormDataListAnalysisDataHelp.getLinkDataField(linkAttrSet, linkDataSet, subFormLinkDataMap);
            Map<String, Object> linkDataIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Set<Object> linkDataIdSet = new HashSet<>();
            for (PaasFormDataEntityExt paasFormDataEntityExt : formDataEsList) {

                // 这个好难啊
                FormDataListAnalysisDataHelp.getLinkDataSet(paasFormDataEntityExt.getData(), subFormLinkDataMap, linkDataSet, linkDataIdSet, linkAttrSet, linkDataIdMap);
            }

            // 非工单解释
            Map<String, PaasFormExplainEntity> formExplainMap = getExplainMapByFormIdList(formIdList, linkResultDataDTO.getCorpid());
            // 工单解释
            Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = getWorkOrderExplainMapByFormId(workOrderFormIdList, linkResultDataDTO.getCorpid());

            // 获取关联数据字段所需要的数据
            linkResultDataVO.setLinkDataSet(linkDataIdSet);
            linkResultDataVO.setLinkData(linkDataIdMap);
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkData4Field(linkResultDataDTO, linkResultDataVO);
            resultDataMap.put(StringConstant.JSON_DATA, formDataMap);
            List<PaasFormDataEntityExt> resultFormDataList = new ArrayList<>();

            for (PaasFormDataEntityExt item : formDataEsList) {
                JSONObject data = item.getData();

                // 先处理子表单的关联数据
                Iterator<String> iterator = subFormLinkDataMap.keySet().iterator();
                while (iterator.hasNext()) {
                    String key = iterator.next();
                    FieldAttrEntity fieldAttrEntity = explainMap.get(key);
                    if (fieldAttrEntity == null) {
                        continue;
                    }
                    Map<String, FieldAttrEntity> subFieldMap = ExplainUtil.getExplainMapByList(fieldAttrEntity.getSubForm().getItems());
                    JSONArray jsonArray = data.getJSONArray(key);
                    if (Objects.nonNull(jsonArray)) {
                        for (int i = 0; i < jsonArray.size(); i++) {
                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                            Set<String> list = subFormLinkDataMap.get(key);
                            for (String subAttr : list) {
                                FieldAttrEntity subField = subFieldMap.get(subAttr);
                                if (subField == null || Objects.isNull(jsonObject.get(subAttr))) {
                                    continue;
                                }
                                if (jsonObject.get(subAttr) instanceof Number && Objects.equals(0L, jsonObject.getLong(subAttr))) {
                                    continue;
                                }
                                if (jsonObject.get(subAttr) instanceof JSONArray || jsonObject.get(subAttr) instanceof ArrayList || jsonObject.get(subAttr) instanceof List) {
                                    List<Long> dataArray = new ArrayList<>();
                                    try {
                                        dataArray = JSON.parseArray(jsonObject.getString(subAttr), Long.class);
                                    } catch (Exception e) {
                                        LOG.error("关联数据多选解析异常", e);
                                    }
                                    if (Objects.equals(dataArray.size(), 0)) {
                                        continue;
                                    }
                                }
                                getLinkDataPrimary(linkResultDataDTO, subField, jsonObject, formDataMap, linkResultDataVO, formExplainMap, workOrderFormExplainMap, subExplainMap);
                            }
                        }
                    }

                }

                // 在处理主数据的关联数据
                for (String key: linkDataSet) {
                    FieldAttrEntity fieldAttrEntity = explainMap.get(key);
                    if (fieldAttrEntity == null) {
                        continue;
                    }
                    getLinkDataPrimary(linkResultDataDTO, fieldAttrEntity, data, formDataMap, linkResultDataVO, formExplainMap, workOrderFormExplainMap, subExplainMap);
                }
                item.setData(data);
                resultFormDataList.add(item);
            }
            linkResultDataVO.setFormDataList(resultFormDataList);
        } catch (Exception e) {
            LOG.error("获取关联数据失败，", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return resultDataMap;
    }

    /**
     * 关联数据列表的解析关联数据的方法
     * @param linkResultDataDTO
     * @param linkResultDataVO
     * @return
     * @throws XbbException
     */

    public List<FormDataVO> formDataLinkDataGet(LinkResultDataDTO linkResultDataDTO, LinkDataPojo linkResultDataVO) throws XbbException {
        List<FormDataVO> resultFormDataList = new ArrayList<>();
        try {
            Map<String, FieldAttrEntity> explainMap = linkResultDataVO.getExplainMap();
            Map<String, Map<String, FieldAttrEntity>> subExplainMap = new HashMap<>(linkResultDataVO.getExplainList().size());
            Set<String> linkAttrSet = new HashSet<>();
            linkResultDataVO.getExplainList().forEach(item->{
                if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType())) {
                    linkAttrSet.add(item.getAttr());
                }
            });
            List<LinkInfoPojo> linkInfoList = ProFormHelp.getLinkInfo(linkResultDataVO.getExplainList());
            List<Long> formIdList = new ArrayList<>();
            List<Long> workOrderFormIdList = new ArrayList<>();
            for (LinkInfoPojo linkInfoPojo : linkInfoList) {
                if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                    workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
                } else {
                    formIdList.add(linkInfoPojo.getLinkFormId());
                }
            }
            // 非工单解释
            Map<String, PaasFormExplainEntity> formExplainMap = getExplainMapByFormIdList(formIdList, linkResultDataDTO.getCorpid());
            // 工单解释
            Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = getWorkOrderExplainMapByFormId(workOrderFormIdList, linkResultDataDTO.getCorpid());

            // 获取关联数据字段所需要的数据
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkData4Field(linkResultDataDTO, linkResultDataVO);

            List<FormDataVO> formDataEsList = linkResultDataVO.getFormDataVOList();
            for (FormDataVO item : formDataEsList) {
                JSONObject data = item.getData();
                for (String key: linkAttrSet) {
                    FieldAttrEntity fieldAttrEntity = explainMap.get(key);
                    if (fieldAttrEntity == null) {
                        continue;
                    }
                    getLinkDataPrimary(linkResultDataDTO, fieldAttrEntity, data,  formDataMap, linkResultDataVO, formExplainMap, workOrderFormExplainMap,subExplainMap );
                }
                item.setData(data);
                resultFormDataList.add(item);
            }
        } catch (Exception e) {
            LOG.error("获取关联数据失败，", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return resultFormDataList;
    }
    /**
     * 获取关联的主键数据
     * @param fieldAttrEntity 字段
     * @param data 数据
     * @param formDataMap 关联数据字段的数据容器
     * @param linkResultDataVO 一些封装数据
     * @param formExplainMap 关联数据字段关联表的字段解释
     * @throws XbbException
     */
    public void getLinkDataPrimary(LinkResultDataDTO linkResultDataDTO, FieldAttrEntity fieldAttrEntity, JSONObject data, Map<String, PaasFormDataEntityExt> formDataMap, LinkResultDataVO linkResultDataVO, Map<String, PaasFormExplainEntity> formExplainMap, Map<String, WorkOrderExplainEntity> workOrderExplainMap, Map<String, Map<String, FieldAttrEntity>> subExplainMap ) throws XbbException {
        Map<String, UserEntity> userMap = linkResultDataVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = linkResultDataVO.getDepartmentMap();
        String key = fieldAttrEntity.getAttr();
        if (FieldTypeEnum.SUB_FORM.getType().equals(fieldAttrEntity.getFieldType()) || FieldTypeEnum.SELECT_PRODUCT.getType().equals(fieldAttrEntity.getFieldType())) {
            List<? extends FieldAttrEntity> subFieldList = fieldAttrEntity.getSubForm().getItems();
            Set<String> linkAttrSet = new HashSet<>();
            subFieldList.forEach(item->{
                if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), item.getFieldType())) {
                    linkAttrSet.add(item.getAttr());
                }
            });
            JSONArray jsonArray = data.getJSONArray(key);
            jsonArray = Objects.isNull(jsonArray) ? new JSONArray() : jsonArray;
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject subJsonObject = jsonArray.getJSONObject(i);
                for (String attr : linkAttrSet) {
                    // 关联单选的value是个数值，关联多选的value是个数组
                    Object value = subJsonObject.get(attr);
                    Object object = getPrimaryKeyField(linkResultDataDTO, subExplainMap.get(key).get(attr), formDataMap, formExplainMap, workOrderExplainMap, value, userMap, departmentMap);
                    if (object == null) {
                        continue;
                    }
                    subJsonObject.put(attr, object);
                }
            }
            data.put(key, jsonArray);
        } else if (FieldTypeEnum.LINK_DATA.getType().equals(fieldAttrEntity.getFieldType()) || FieldTypeEnum.LINK_DATA_MULTI.getType().equals(fieldAttrEntity.getFieldType())) {
            // 关联单选的value是个数值，关联多选的value是个数组
            Object value = data.get(key);
            Object object = getPrimaryKeyField(linkResultDataDTO, fieldAttrEntity, formDataMap, formExplainMap, workOrderExplainMap, value, userMap, departmentMap);
            if (object == null) {
                data.put(key, null);
                return;
            }
            data.put(key, object);
        } else {
            data.put(key, data.get(key));
        }
    }
}
